package com.thp.strategy.examplePro1;

import java.io.File;
import java.io.FileFilter;
import java.lang.annotation.Annotation;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.List;

/**
 * 策略工厂
 * @author Tommy
 *
 */
public class CalPriceFactory {

	// 需要扫描的包
	private static final String CAL_PRICE_PACKEGE = "com.thp.strategy.examplePro1";
	
	// 获取类加载器
	private ClassLoader classLoader = getClass().getClassLoader();
	
	private List<Class<? extends CalPrice>> calPriceList;  // 策略列表
	
	
	
	
	
	// 根据客户的总金额产生相应的金额
	public  CalPrice createPrice(Player customer) {
		// 在策略列表中查找
		for(Class<? extends CalPrice> clazz : calPriceList) {
			// 获取该策略的注解
			PriceRegion validRegion = handleAnnotation(clazz);
			// 判断金额是否是在注解区间
			if(customer.getTotalMount() > validRegion.min() && customer.getTotalMount() < validRegion.max()) {
				try {
					// 是的话我们就返回一个当前 的策略
					return clazz.newInstance();
				} catch (InstantiationException | IllegalAccessException e) {
					throw new RuntimeException("策略获取失败");
				}
			}
		}
		throw new RuntimeException("策略获取失败");
	}
	
	/**
	 * 需要获取类的注解
	 * 处理注解,我们传入有一个策略类,返回它的注解
	 * @return
	 */
	private PriceRegion handleAnnotation(Class<? extends CalPrice> clazz) {
		Annotation[] annotations = clazz.getDeclaredAnnotations();
		if(annotations == null || annotations.length == 0) {
			return null;
		}
		for(int i = 0; i < annotations.length; i++) {
			if(annotations[i] instanceof PriceRegion) {
				return (PriceRegion) annotations[i];
			}
		}
		return null;
	}
	
	// 单例
	private CalPriceFactory() {
		init();
	}
	
	// 在策略工厂初始化的时候需要初始化策略列表
	private void init() {
		calPriceList = new ArrayList<Class<? extends CalPrice>>();
		// 获取到包下面的所有的.class文件
		File[] resources = getResource();
		Class<CalPrice> calPriceClazz = null;
		
		// 使用相同的类加载器加载策略接口
		try {
			calPriceClazz = (Class<CalPrice>) classLoader.loadClass(CalPrice.class.getName());
		} catch (ClassNotFoundException e) {
			throw new RuntimeException("未找到策略接口");
		}
		for(int i = 0; i < resources.length; i++) {
			try {
				// 加载扫描的包下面的类   使用的是classLoader.loadClass()方法 是不会进行初始化的
				Class<?> clazz = classLoader.loadClass(CAL_PRICE_PACKEGE + "." + resources[i].getName().replace(".class", ""));
				// 判断是否是CalPrice的实现类并且不是CalPrice这个接口本身,如果满足的话,那么就加入到策略列表
				if(CalPrice.class.isAssignableFrom(clazz) && clazz != calPriceClazz) {
					calPriceList.add((Class<? extends CalPrice>) clazz);
				}
			} catch (ClassNotFoundException e) {
				e.printStackTrace();
			}
		}
		
	}
	
	
	// 获取扫描的包下面的所有的class文件
	private File[] getResource() {
		try {
			File file = new File(classLoader.getResource(CAL_PRICE_PACKEGE.replace(".", "/")).toURI());
			return file.listFiles(new FileFilter() {
				@Override
				public boolean accept(File pathname) {  // 只需要扫描.class文件
					if(pathname.getName().endsWith(".class")) {
						return true;
					}
					return false;
				}
			});
		} catch (URISyntaxException e) {
			throw new RuntimeException("未找到策略源");
		}
		
	}
	
	
	
	
	
	// 静态内部类的方式  实现单例模式
	public static CalPriceFactory getInstance() {
		return ClaPriceFactoryInstance.instance;
	}
	
	private static class ClaPriceFactoryInstance {
		private static CalPriceFactory instance = new CalPriceFactory();
	}
	
	
	
}
